Data Sheet - 21st May 2011
              _______         _           ______         _   _     
             |__   __|       | |         |  ____|       | | | |    
                | |_   _ _ __| |__   ___ | |__ ___  _ __| |_| |__  
                | | | | | '__| '_ \ / _ \|  __/ _ \| '__| __| '_ \ 
                | | |_| | |  | |_) | (_) | | | (_) | |  | |_| | | |
                |_|\__,_|_|  |_.__/ \___/|_|  \___/|_|   \__|_| |_|
                                                                   
                                                                   
          _____                       _  __          __           _     
         / ____|                     | | \ \        / /          | |    
        | (___   ___  _   _ _ __   __| |  \ \  /\  / /__  _ __ __| |___ 
         \___ \ / _ \| | | | '_ \ / _` |   \ \/  \/ / _ \| '__/ _` / __|
         ____) | (_) | |_| | | | | (_| |    \  /\  / (_) | | | (_| \__ \
        |_____/ \___/ \__,_|_| |_|\__,_|     \/  \/ \___/|_|  \__,_|___/
                                                                        
Unfortunately, due to space constraints TurboForth contains no support for 
sound in its built in ROM. However, it is very easy to add supporting words
to your program to allow your program to access all three tone generators and
the noise generator of the TMS9919/SN94624 fitted into all 4A consoles.

The following definitions provide sound support:

: VOLUME ( ch# vol  -- )
  \ set volume of channel ch# to vol
  $F AND SWAP 2* 1+ 8 + 4 << OR $8400 C! ;

: TONE ( ch# freq -- )
  \ set freq of channel ch# to freq
  SWAP 2* 8 + 4 << SWAP DUP $F AND ROT OR SWAP 4 >> SWAP
  $8400 C! $8400 C! ;

: NOISE ( n -- )
  \ set noise generator to noise type n 
  7 AND $E0 OR $8400 C! ;
 
To use:

0 1017 TONE
Will play a low A on channel 0
Note: the codes for the notes can be found in Editor Assembler, page 318-320)

0 0 VOLUME will set channel 0 to maximum volume (15 is off).

Here is an A chord:

0 1017 TONE
1 807  TONE
2 679  TONE

Then set the volume:

0 0 VOLUME
1 0 VOLUME
2 0 VOLUME

Note: You only have to set the volume for each channel once. Unless you want to 
change the volume, of course.

To stop a tone from playing, set its volume to 15.

Here is a test program:

1 VALUE STEP
: TEST 0 0 VOLUME  1017 20 DO 0 I TONE STEP +LOOP 0 15 VOLUME ;

Now, you can play around like this:

1 TO STEP  TEST
2 TO STEP  TEST
10 TO STEP  TEST

etc etc

The noise channel takes a value from 0 to 7 for the different types of noise. 
Use a value of 3 for the channel number number when you want to change the 
volume of the noise channel.

[ UPDATED 3rd AUGUST 2015 - MRW ]
Assembly language and Machine Code equivalents of the above:
------------------------------------------------------------

asm: volume ( ch# vol -- )
    \ set the volume on sound channel ch# to vol
    *sp+ r0 mov,        \ pop volume
    r0 $F andi,         \ mask out any crap
    *sp+ r1 mov,        \ get channel
    r1 1 sla,           \ multiply by two
    r1 9 ai,            \ add 9
    r1 4 sla,           \ shift 4 bits to left
    r0 r1 soc,          \ or them together
    r1 swpb,            \ move to high byte
    r1 $8400 @@ movb,   \ poke sound chip
;asm
CODE: volume ( ch# vol -- )
\ set the volume on sound channel ch# to vol
C034 0240 000F C074 0A11 0221 0009 0A41 E040 06C1 D801 8400
;CODE 

asm: noise ( n -- )
    \ set noise generator to noise type n
    *sp+ r0 mov,        \ get n
    r0 7 andi,          \ mask
    r0 $E0 ori,         \ set noise bit
    r0 swpb,            \ into high-byte
    r0 $8400 @@ movb,   \ poke sound chip
;asm
CODE: noise ( n -- )
\ set noise generator to noise type n
C034 0240 0007 0260 00E0 06C0 D800 8400 ;CODE
 
asm: tone ( ch# freq -- )
    \ set tone channel ch# to frequency freq
    *sp+ r1 mov,        \ freq
    *sp+ r2 mov,        \ ch
    r2 1 sla,           \ ch*2
    r2 8 ai,            \ +8
    r2 4 sla,           \ << 4
    r1 r0 mov,          \ copy freq
    r0 $F andi,         \ mask
    r0 r2 soc,          \ or freq & ch
    r1 4 srl,           \ move into position
    r2 swpb,            \ into high-byte
    r1 swpb,            \ into high-byte 
    r2 $8400 @@ movb,   \ poke sound chip
    r1 $8400 @@ movb,   \ poke sound chip 
;asm
CODE: tone ( ch# freq -- )
\ set tone channel ch# to frequency freq
C074 C0B4 0A12 0222 0008 0A42 C001 0240 000F E080 0941 06C2
06C1 D802 8400 D801 8400 ;CODE
